package com.strong.system.constroller;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.strong.utils.JSON;
import com.strong.utils.mvc.pojo.view.ReplyVO;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.servlet.ModelAndView;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import static com.strong.utils.mvc.pojo.view.ReplyEnum.*;

/**
 * 系统异常控制器
 *
 * @author simen
 * @date 2022/02/17
 */
@Slf4j
public class SystemErrorController extends BasicErrorController {

//    /**
//     * 异常消息map
//     */
//    public final static Map<String, String> MAP_EXCEPTION_MESSAGE = new HashMap<>();
//
//    static {
//        MAP_EXCEPTION_MESSAGE.put(IllegalArgumentException.class.getName(), "提交的参数异常");
//        MAP_EXCEPTION_MESSAGE.put(MethodArgumentNotValidException.class.getName(), "提交的数据无效");
//        MAP_EXCEPTION_MESSAGE.put(EntityNotFoundException.class.getName(), "数据库实体异常");
//        MAP_EXCEPTION_MESSAGE.put(AccessDeniedException.class.getName(), "未授权或登录已超时");
//        MAP_EXCEPTION_MESSAGE.put(SQLIntegrityConstraintViolationException.class.getName(), "数据库处理异常");
//        MAP_EXCEPTION_MESSAGE.put(IllegalStateException.class.getName(), "非法状态异常");
//        MAP_EXCEPTION_MESSAGE.put(DataIntegrityViolationException.class.getName(), "数据完整性检查异常");
//        MAP_EXCEPTION_MESSAGE.put(BadCredentialsException.class.getName(), "用户验证失效");
//    }


//    /**
//     * 异常消息map
//     */
//    public final static Map<String, ReplyEnum> MAP_EXCEPTION_MESSAGE = new HashMap<>();
//
//    static {
//        MAP_EXCEPTION_MESSAGE.put(IllegalArgumentException.class.getName(), ERROR_SERVER_ILLEGAL_ARGUMENT_EXCEPTION);
//        MAP_EXCEPTION_MESSAGE.put(MethodArgumentNotValidException.class.getName(),ERROR_SERVER_METHOD_ARGUMENT_NOT_VALID_EXCEPTION);
//        MAP_EXCEPTION_MESSAGE.put(EntityNotFoundException.class.getName(), ERROR_SERVER_ENTITY_NOT_FOUND_EXCEPTION);
//        MAP_EXCEPTION_MESSAGE.put(AccessDeniedException.class.getName(), ERROR_SERVER_ACCESS_DENIED_EXCEPTION);
//        MAP_EXCEPTION_MESSAGE.put(SQLIntegrityConstraintViolationException.class.getName(), ERROR_SERVER_SQL_INTEGRITY_CONSTRAINT_VIOLATION_EXCEPTION);
//        MAP_EXCEPTION_MESSAGE.put(IllegalStateException.class.getName(), ERROR_SERVER_ILLEGAL_STATE_EXCEPTION);
//        MAP_EXCEPTION_MESSAGE.put(DataIntegrityViolationException.class.getName(), ERROR_SERVER_DATA_INTEGRITY_VIOLATION_EXCEPTION);
//        MAP_EXCEPTION_MESSAGE.put(BadCredentialsException.class.getName(), ERROR_SERVER_BAD_CREDENTIALS_EXCEPTION);
//    }

    /**
     * 实例化
     *
     * @param errorAttributes    错误属性
     * @param errorProperties    错误属性
     * @param errorViewResolvers 错误视图解析器
     */
    public SystemErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties, List<ErrorViewResolver> errorViewResolvers) {
        super(errorAttributes, errorProperties, errorViewResolvers);
    }

    /**
     * 错误html响应
     *
     * @param request  请求
     * @param response 响应
     * @return {@link ModelAndView}
     */
    @Override
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = getStatus(request);
        int intStatusCode = status.value();
        response.setStatus(intStatusCode);
        Map<String, Object> map = Collections.unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML)));
        ModelAndView view = new ModelAndView("errorHtml");
        view.addAllObjects(map);

        if (intStatusCode == 404) {
            view.addObject("error", "抱歉，您所请求的页面不存在！");
        } else if (intStatusCode > 400 && intStatusCode < 500) {
            view.addObject("error", "抱歉，您没有访问该页面的权限！");
        } else {
            view.addObject("error", "抱歉，服务器发生错误！");
        }
        log.info("HTML请求返回错误：{}", map);

        return view;
    }

    /**
     * 错误其他响应
     *
     * @param request 请求
     * @return {@link ResponseEntity}<{@link Map}<{@link String}, {@link Object}>>
     */
    @Override
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        HttpStatus status = this.getStatus(request);
        if (status == HttpStatus.NO_CONTENT) {
            return new ResponseEntity<>(JSON.toMap(new ReplyVO<>(SUCCESS_RETURN_DATA.getMsg(), SUCCESS_CONTENT_BLANK.getMsg(), status.value())), HttpStatus.OK);
        } else {
            Map<String, Object> body = this.getErrorAttributes(request, this.getErrorAttributeOptions(request, MediaType.ALL));

            log.info("非HTML请求返回错误：{}", body);

            // 获取http返回状态码
            Integer intStatus = MapUtil.getInt(body, "status");
            // 获取http返回的异常字符串
            String strException = MapUtil.getStr(body, "exception");
            // 获取http返回的异常字符串
            String strTrace = MapUtil.getStr(body, "trace");
            // 返回对象的消息
            String strMsg = ERROR_SERVER_ERROR.getMsg();
            // 返回对象的内容
            String strData = StrUtil.isBlank(strTrace) ? strException : StrUtil.subBetween(strTrace, ":", "\n").trim();

            return new ResponseEntity<>(JSON.toMap(new ReplyVO<>(strData, strMsg, intStatus)), HttpStatus.OK);
        }
    }

//    /**
//     * 错误其他响应
//     *
//     * @param request 请求
//     * @return {@link ResponseEntity}<{@link Map}<{@link String}, {@link Object}>>
//     */
//    @Override
//    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
//        HttpStatus status = this.getStatus(request);
//        if (status == HttpStatus.NO_CONTENT) {
//            return new ResponseEntity<>(JSON.toMap(new ReplyVO<>(SUCCESS_RETURN_DATA.getMsg(), SUCCESS_CONTENT_BLANK.getMsg(), status.value())), HttpStatus.OK);
//        } else {
//            Map<String, Object> body = this.getErrorAttributes(request, this.getErrorAttributeOptions(request, MediaType.ALL));
//
//            log.info("非HTML请求返回错误：{}", body);
//
//            // 获取http返回状态码
//            Integer intStatus = MapUtil.getInt(body, "status");
//            // 获取http返回的异常字符串
//            String strException = MapUtil.getStr(body, "exception");
//            // 获取http返回的异常字符串
//            String strTrace = MapUtil.getStr(body, "trace");
//            // 返回对象的消息
//            String strMsg = ERROR_SERVER_ERROR.getMsg();
//            // 返回对象的内容
//            String strData = StrUtil.subBetween(strTrace, ":", "\n").trim();
//
//            // 直接从request中获取STR_JAKARTA_SERVLET_ERROR_EXCEPTION对象
//            Object objErrorException = request.getAttribute(ORG_SPRINGFRAMEWORK_BOOT_WEB_SERVLET_ERROR_DEFAULTERRORATTRIBUTES_ERROR);
//
////            Iterator<String> iterator = request.getAttributeNames().asIterator();
////            while (iterator.hasNext()) {
////                String strKey = iterator.next();
////                System.out.println(String.format("%s: %s", strKey, request.getAttribute(strKey)));
////            }
//
//            // 1. 使用request的STR_JAKARTA_SERVLET_ERROR_EXCEPTION值获取错误消息
//            // 判断异常对象是否为空
//            if (ObjUtil.isNotNull(objErrorException)) {
//                List<String> lisErrorException = StrUtil.splitTrim(objErrorException.toString(), ":");
//                if (lisErrorException.size() == 2) {
//                    String strExceptionName = lisErrorException.get(0);
//                    if (StrUtil.equalsAny(strExceptionName, StrongRuntimeException.class.getName(), StrongException.class.getName())) {
//                        strMsg = "服务器返回异常";
//                        strData = lisErrorException.get(1);
//                    } else {
//                        String strTemp = MAP_EXCEPTION_MESSAGE.get(strExceptionName);
//                        if (StrUtil.isNotBlank(strTemp)) {
//                            strMsg = strTemp;
//                            strData = lisErrorException.get(1);
//                        }
//                    }
//                }
//            }
//
//            // 2. 使用request的exception字符串获取错误消息
//            // 判断replyVO.getData()为空，且http返回的异常字符串是否为空
//            if (StrUtil.isBlank(strData) && StrUtil.isNotBlank(strException)) {
//                strData = MAP_EXCEPTION_MESSAGE.get(strException);
//            }
//
//            // 3. 使用request的exception字符串获取错误消息
//            // 判断replyVO.getData()为空，且错误代码有效
//            if (StrUtil.isBlank(strData) && intStatus > 0) {
//                ReplyEnum replyEnum = EnumUtil.getBy(ReplyEnum.class,
//                        re -> re.getCode().equals(intStatus));
//                // 判断错误代码获取到的枚举类是否存在
//                if (ObjUtil.isNotNull(replyEnum)) {
//                    strData = replyEnum.getMsg();
//                }
//            }
//
//            // 4. 使用默认错误消息
//            // 判断replyVO.getData()为空
//            if (StrUtil.isBlank(strData)) {
//                // 默认返回的错误内容
//                strData = LOGIN_ERROR_UNKNOWN;
//            }
//
//            return new ResponseEntity<>(JSON.toMap(new ReplyVO<>(strData, strMsg, intStatus)), HttpStatus.OK);
//        }
//    }
}
